//	ID: 066498650
//	Exercise #: 2
//	By:	Roy Moore
//
//	Written:	19/12/2011
//	Environment : VS2010
//
//-UDPTime.cpp-

#include "UDPTime.h"

string serviceName[NUMOFSERVICES];
//------------------Functions-----------------------------------------------
void InitserviceName(){
	serviceName[0] = "a. Get Time";
	serviceName[1] = "b. GetTimeWithoutYear";
	serviceName[2] = "c. GetTimeSinceEpoch";
	serviceName[3] = "d. GetClientToServerDelayEstimation";
	serviceName[4] = "e. MeasureRTT";
	serviceName[5] = "f. GetDayAndMounth";
	serviceName[6] = "g. Get Year";
}

SOCKET InitUDPConnection(){
	WSAData wsaData; 

	if (NO_ERROR != WSAStartup(MAKEWORD(2,2), &wsaData))
	{
        cout << "Time Server: Error at WSAStartup()" << endl;
	}

    SOCKET connSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

	if (INVALID_SOCKET == connSocket)
	{
        cout << "Time Server: Error at socket(): " <<WSAGetLastError() << endl;
        WSACleanup();
        exit(EXIT_FAILURE);
	}

	return connSocket;
}

void BindSocketForServer(SOCKET connSocket){
	sockaddr_in serverService;
    serverService.sin_family = AF_INET; 
	serverService.sin_addr.s_addr = INADDR_ANY;
	serverService.sin_port = htons(TIME_PORT);

    if (SOCKET_ERROR == bind(connSocket, (SOCKADDR *) &serverService, sizeof(serverService))) 
	{
		cout << "Time Server: Error at bind(): "<< WSAGetLastError() << endl;
		ExitAndCloseSocket(connSocket, EXIT_FAILURE);
    }
}

MsgInfo InitMsgInfo(){
	MsgInfo tempMsgInfo;

	tempMsgInfo.bytesRecv = 0;
	tempMsgInfo.bytesSent = 0;

	return tempMsgInfo;
}

void RecvDataFrom(SOCKET connSocket, MsgInfo *info, sockaddr *from_addr){
	int bytesRecv;
	int addr_len = sizeof(*from_addr);

	bytesRecv = recvfrom(connSocket, info->recvBuff, BUFFER_SIZE, 0, from_addr, &addr_len);

	if (SOCKET_ERROR == bytesRecv)
	{
		cout << "Time Server: Error at recvfrom(): " << WSAGetLastError()<<endl;
		ExitAndCloseSocket(connSocket, EXIT_FAILURE);
	}

	info->recvBuff[bytesRecv] = '\0'; //End String
	info->bytesRecv = bytesRecv; //Update bytesRecv counter
}

void SendDataTo(SOCKET connSocket, MsgInfo *info, sockaddr * to_addr){
	int bytesSent;
	int addr_len = sizeof(*to_addr);
	int sendBuffLen = (int)strlen(info->sendBuff);

	bytesSent = sendto(connSocket, info->sendBuff, sendBuffLen, 0, (const sockaddr *)to_addr, addr_len);

	if (SOCKET_ERROR == bytesSent)
	{
		cout << "Time Client: Error at sendto(): " << WSAGetLastError() << endl;
		ExitAndCloseSocket(connSocket, EXIT_FAILURE);
	}

	info->bytesSent = bytesSent; //Update bytesSent counter
}

void RecvData(SOCKET connSocket, MsgInfo *info){
	int bytesRecv;

	bytesRecv = recv(connSocket, info->recvBuff, BUFFER_SIZE, 0);

	if (SOCKET_ERROR == bytesRecv)
	{
		cout<<"Time Client: Error at recv(): "<< WSAGetLastError()<< endl;
		ExitAndCloseSocket(connSocket, EXIT_FAILURE);
	}

	info->recvBuff[bytesRecv] = '\0'; //End String
	info->bytesRecv = bytesRecv; //Update bytesRecv counter
}

void ExitAndCloseSocket(SOCKET connSocket, int _code){
	    closesocket(connSocket);
		WSACleanup();
        exit(_code);
}

void PrintStatus(ROLE role, MODE mode, int bytes, char* buff){
	//cout << "Time Client: Recieved: " << info->bytesRecv << " bytes of \"" << info->recvBuff << "\" message." << endl;
	//cout << "Time Server: Recieved: " << serverMsgInfo.bytesRecv << " bytes of \"" << serverMsgInfo.recvBuff << "\" message." << endl;
	//cout<< "Time Client: Sent: " << info->bytesSent << "/" << strlen(info->sendBuff) << " bytes of \"" <<info->sendBuff << "\" message." << endl;
	//cout << "Time Server: Sent: " << serverMsgInfo.bytesSent << "\\" << strlen(serverMsgInfo.sendBuff) << " bytes of \"" << serverMsgInfo.sendBuff << "\" message." << endl;	

	string msgStr;
	char tempIntToStr[BUFFER_SIZE];

	msgStr.append("Time ");

	if (role == Server)
		msgStr.append("Server: ");
	else
		msgStr.append("Client: ");

	if (mode == Send){
		msgStr.append("Sent: ");
		sprintf(tempIntToStr, "%d", bytes);
		msgStr.append(tempIntToStr);

		msgStr.append("/");
		sprintf(tempIntToStr, "%d", strlen(buff));
		msgStr.append(tempIntToStr);

		msgStr.append(" bytes of \"");
		msgStr.append(buff);
		msgStr.append("\" msg");
	}
	else if(mode = Recive){
		msgStr.append("Recived: ");
		sprintf(tempIntToStr, "%d", bytes);
		msgStr.append(tempIntToStr);

		msgStr.append(" bytes of \"");
		msgStr.append(buff);
		msgStr.append("\" msg");
	}
	else msgStr = "Unexpected Error";

	cout << msgStr << endl;
}